package javaClassExercise.newObjectStyle;

import java.lang.reflect.Constructor;

/**
 * Created by lomo.
 *
 * 推荐使用 通过Constructor.newInstance()创建新的类实例
 */
public class demoTest {

    public static void main(String[] args) {
        demoTest demoTest = new demoTest();
        System.out.println("通过Class.NewInstance()调用私有构造函数:");
        demoTest.newInstanceByClassNewInstance();   //失败, 如果无参构造器为public的就可以调用.

        System.out.println("通过Constructor.NewInstance()调用私有构造函数:");
        demoTest.newInstanceByConstructorNewInstance();  // 同时调用demo类的无参和有参构造器
        //输出：
        // demo's constructor is called.
        // 9

    }

    /*通过Class.NewInstance()创建新的类示例*/
    public void newInstanceByClassNewInstance() {
        try {
            /* 当前包名为javaClassExercise.newObjectStyle，必须使用全路径 */
            demo demo = (demo)Class.forName("javaClassExercise.newObjectStyle.demo").newInstance();
        }catch (Exception e) {
            System.out.println("通过Class.NewInstance()调用私有构造函数【失败】");
            //e.printStackTrace();
        }
    }

    /*通过Constructor.newInstance()创建新的类示例*/
    public void newInstanceByConstructorNewInstance() {
        try {

            Class c = Class.forName("javaClassExercise.newObjectStyle.demo");


            Constructor c0 = c.getDeclaredConstructor();  // 获得构造器对象
            c0.setAccessible(true); // 关闭JDK安全检查，提升反射速度
            //关于setAccessible，https://my.oschina.net/swearyd7/blog/167822

            //调用私有、无参构造函数
            demo demo0 = (demo)c0.newInstance();
            demo0.printSth("lomo");

            demo0.printa(6666);  // protected级别的可以直接调用
            //printa 这个private级别的方法无法被直接调用

            /*
            Method[] c2 = c.getDeclaredMethods();
            for(int i = 0; i < c2.length; i++) {
                //System.out.println("函数名：" + c2[i].getName()); //获得除构造器以外的所有函数名，包括private
                //System.out.println("函数名：" + c2[i].getReturnType()); //获得除构造器以外的所有函数的返回类型，包括private
                //System.out.println("函数名：" + c2[i]);  // 获得所有方法(除构造器)的方法体不包括{}
                System.out.println("函数名：" + Modifier.toString(c2[i].getModifiers()));  // 获得所有函数的访问权限
            }
            */



            /* 调用参数、私有构造函数*/
            //传入参数
            Constructor c1 = c.getDeclaredConstructor(new Class[] {int.class, int.class});
            c1.setAccessible(true);
            demo demo1 = (demo)c1.newInstance(new Object[]{4,5});
            demo1.printSth();


        }catch (Exception e) {
            System.out.println("通过Constructor.NewInstance()调用私有构造函数【失败】");
            //e.printStackTrace();
        }
    }
}
